Skip to content

feat: evaluate UTF8 array extrema collations natively - #6170

Open
sunchao wants to merge 11 commits into
apache:mainfrom
sunchao:dev/chao/codex/native-array-extrema-utf8-collations
Open

sunchao wants to merge 11 commits into
apache:mainfrom
sunchao:dev/chao/codex/native-array-extrema-utf8-collations

Conversation

@sunchao

@sunchao sunchao commented Sep 24, 2026 •

Copy link
Copy Markdown
Member

Which issue does this PR close?

Part of #4496. Depends on #5403, currently at ae755c459e0acd95f72a53f538d959e2adec572c; rebase after it lands. The incremental follow-up diff starts after merging #5403 with this PR's main base.

Rationale for this change

#5403 uses Spark's JVM dispatcher for collated array_min/array_max. This follow-up evaluates the UTF8 collation family in Rust, including strings nested in arrays and structs. For example, array_min of ['a', 'B'] under UTF8_LCASE returns the original 'a' using the native extrema comparator.

What changes are included in this PR?

  • Carry string-leaf collation metadata into the existing extrema comparator. Support UTF8_BINARY, UTF8_BINARY_RTRIM, UTF8_LCASE, and UTF8_LCASE_RTRIM, preserving the original first winner on ties.
  • Pin unicode-case-mapping 1.0.0 for Unicode 16, with Spark's sigma rule and Unicode 17 additions. Unsupported collations or Unicode versions retain the existing dispatch/fallback and incompatible opt-in behavior.
  • Preserve existing cast and scan support boundaries. Input collation casts may use the JVM dispatcher while extrema execute natively.
  • Keep SQL coverage for supported modes and mixed nested collations, with focused JVM coverage for result metadata, NaN bits, and fallback boundaries. Add native and Spark benchmarks covering string lengths, Unicode, and null density.

How are these changes tested?

At 895838be7bbb2eaf24da0ba28cf43ca4268e5b36:

  • Native extrema tests: 11 passed.
  • Spark 4.1 with a freshly built JNI library: 5 tests passed, covering three focused extrema tests, the array_extrema_collation.sql fixture, and the collation-cast fallback regression.
  • Workspace/all-target Clippy with warnings denied, Spotless, ScalaStyle, Apache RAT, and git diff --check passed.
  • All 56 release Criterion cases passed their output checks. This characterizes the final native implementation, which is unchanged from the benchmarked source at 426971841. All 24 release JNI Spark-versus-Comet cases completed, asserting native extrema while allowing existing input-cast dispatch.

Hosted CI is running for this revision. The run-all-spark-profiles and run-spark-4.1-tests labels request the broader suites.

Release benchmark results (Spark 4.1.3, JDK 17, AMD EPYC Milan, local single worker, 262,144 rows):

The table shows Spark/Comet mean-time ratios, ranging across array_min/array_max; above 1 favors Comet. It includes input-cast dispatch and query execution. The binary control retains the existing scalar/DataFusion path.

Input Binary control Binary RTRIM LCASE LCASE RTRIM
short ASCII, no nulls 0.76–0.77x 0.81–0.95x 0.78–0.86x 1.15–1.29x
long ASCII, sparse nulls 0.35–0.51x 0.42–0.42x 1.07–1.14x 1.25–1.47x
Unicode, dense nulls 0.64–0.65x 0.77–0.82x 1.99–2.03x 2.00–2.07x

Results are workload-dependent, with substantial variance in some long-ASCII Comet cases. This is one local run of CometArrayExpressionBenchmark.arrayExtremaCollationBenchmark, not a general speedup claim or a before/after measurement of the cast-fallback fix. The native library was built from this commit with the release profile; debug symbols were disabled.

@github-actions github-actions Bot added enhancement New feature or request area:expressions Expression evaluation labels Sep 24, 2026
@sunchao sunchao added run-all-spark-profiles Run the Comet test suites against every Spark profile on this pull request, ahead of the merge queue run-spark-4.1-tests Run the Spark 4.1 SQL tests on this pull request instead of waiting for the merge queue labels Sep 24, 2026
@sunchao
sunchao marked this pull request as ready for review September 24, 2026 22:57

@sunchao sunchao left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

  • Prior state and problem: DataFusion extrema ordering could select different floating-point or nested winners than Spark and did not honor nonbinary collations.
  • Design approach: Share one SparkArrayExtrema implementation, with typed float scans, recursive comparisons, and per-string-leaf collation metadata.
  • Correctness / compatibility analysis: Checked Spark 3.4.3, 3.5.9, 4.0.4, 4.1.3, and the 4.2 branch. First-winner retention, NaNs, signed zeros, nested null ordering, and supported UTF8 collations match the inspected Spark semantics. Unsupported collations retain dispatch/fallback and explicit incompatible opt-in.
  • Key design decisions: Pin Unicode 16 mappings, supplement Unicode 17, preserve original winning values, and keep existing cast/scan boundaries. Comparators are constructed per batch without allocating lowercase strings per comparison.
  • Implementation sketch: Scala serializes collations into ScalarFunc, the planner constructs the configured UDF, and native evaluation copies selected results with bounded retained nested buffers. The abstraction stays local to extrema.
  • Behavioral changes worth calling out: The full stack fixes floating-point and nested ordering in both strict modes and enables native UTF8 collation comparisons. Reported performance remains workload-dependent, including slower cases. I did not independently rerun benchmarks.
  • Suggested improvements: None at P1/P2 priority. No introduced P1/P2 issues found within this review.

Reviewed the entire diff from de2e70291460ed0310428493d8c3aa5223293d08 to d44b19ae53f1048f9d19529b159ff0c227f85c00, including prerequisite commits. Confirmed non-draft status and read the supplied discussion snapshot plus prerequisite discussions. Earlier substantiated concerns are addressed.

Routed skills: review-comet-pr, review-comet-expression-pr, review-comet-ffi-pr (test-only JNI change), and review-comet-memory-pr (nested result allocation).

Exact-head CI: 47 successful checks, 14 skipped, none failed or pending. This includes native tests, 20 Comet suite jobs across Spark 3.4–4.2, and all seven Spark 4.1 SQL shards. Inspected logs confirm the new regressions ran. These checks attach to the requested head, while the workflow tested PR merge ref c1c0282. macOS and other Spark SQL versions were skipped.

Local validation: All 11 focused native extrema tests passed at the pinned head. An isolated check of the exact comparator passed exhaustive Unicode 16/17 mapping validation against ICU data and Spark’s special rules, plus 800,000 string comparisons. git diff --check passed. Local JVM/JNI integration and release benchmarks were not rerun.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:expressions Expression evaluation enhancement New feature or request run-all-spark-profiles Run the Comet test suites against every Spark profile on this pull request, ahead of the merge queue run-spark-4.1-tests Run the Spark 4.1 SQL tests on this pull request instead of waiting for the merge queue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant